package io.cw.service.impl.iml.reservation;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.cw.common.utils.DateUtils;
import io.cw.dao.reservation.ReservationRecordDao;
import io.cw.entity.background.RelRoomSeatEntity;
import io.cw.entity.background.RelRoomTimeEntity;
import io.cw.entity.background.RoomEntity;
import io.cw.entity.background.UserInfoEntity;
import io.cw.entity.reservation.ReservationEntity;
import io.cw.service.impl.background.RelRoomSeatService;
import io.cw.service.impl.background.RelRoomTimeService;
import io.cw.service.impl.background.RoomService;
import io.cw.service.impl.background.UserInfoService;
import io.cw.service.impl.reservation.ReservationRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 预约记录服务类
 *
 * @author cw
 */
@Service
public class ReservationRecordServiceImpl extends ServiceImpl<ReservationRecordDao, ReservationEntity> implements ReservationRecordService {

    @Autowired
    private RoomService roomService;

    @Autowired
    private RelRoomSeatService seatService;

    @Autowired
    private RelRoomTimeService timeService;

    @Autowired
    private EmailServiceImpl emailService;

    @Autowired
    private UserInfoService userInfoService;

    @Override
    public List<ReservationEntity> findAll(String keyWord) {
        List<ReservationEntity> reservationList = this.getBaseMapper().selectByKeyWord(keyWord);

        return reservationList;
    }

    @Override
    @Transactional
    public void signIn(String id) throws Exception {
        Integer status = 0;

        // 获取预约记录
        ReservationEntity reservation = this.lambdaQuery().eq(ReservationEntity::getId, id).eq(ReservationEntity::getIsValid, 1).one();
        if (Objects.isNull(reservation)) throw new Exception("无预约记录");

        // 更新状态
        reservation.setStatus(3);
        this.updateById(reservation);


        Timestamp startTime = reservation.getStartTime();
        Date late = DateUtils.addMinute(startTime, 15);
        Timestamp nowTime = new Timestamp(System.currentTimeMillis());
        if (startTime.before(nowTime) && late.after(nowTime)){
            // 迟到扣分: 15分钟内算迟到
            status = 1;
            userInfoService.subtractScore(reservation.getPhoneNumber(), 10);
        } else if (nowTime.after(late)){
            // 在15分钟后签到, 取消预约
            status = 2;
            this.cancel(id);
        }

        // 更新座位状态: 入
        if (status.equals(0) || status.equals(1)) {
            RelRoomSeatEntity seat = seatService.lambdaQuery().eq(RelRoomSeatEntity::getIsValid, 1).one();
            if (Objects.nonNull(seat)){
                seat.setStatus(3);
                seatService.updateById(seat);
            }
        }
    }


    @Override
    @Transactional
    public void cancel(String seatId) {
        // 获取预约记录
        ReservationEntity reservation = this.lambdaQuery().eq(ReservationEntity::getSeatId, seatId).eq(ReservationEntity::getIsValid, 1).one();
        if (Objects.isNull(reservation)) return;

        // 更新状态
        reservation.setStatus(2);
        this.updateById(reservation);

        // 释放座位: 可预约
        RelRoomSeatEntity seat = seatService.lambdaQuery().eq(RelRoomSeatEntity::getIsValid, 1).one();
        if (Objects.nonNull(seat)){
            seat.setStatus(1);
            seatService.updateById(seat);
        }

    }

    /**
     * 可预约列表
     * @return
     */
    @Override
    public List<RoomEntity> ableReservationList() {
        List<RoomEntity> ableList = new ArrayList<>();
        Timestamp startTime = new Timestamp(DateUtils.getDayStartTime(new Date()).getTime());

        List<RoomEntity> roomList = roomService.findAllList();
        if (CollectionUtils.isEmpty(roomList)) return null;
        List<String> roomIds = roomList.stream().map(RoomEntity::getId).collect(Collectors.toList());

        List<RelRoomSeatEntity> seatList = seatService.lambdaQuery().in(RelRoomSeatEntity::getRoomId, roomIds)
                                                                    .eq(RelRoomSeatEntity::getIsValid, 1)
                                                                    .orderByAsc(RelRoomSeatEntity::getSeatNo)
                                                                    .list();

        // 过滤今天以及今天之后 时段数据
        for (RoomEntity room : roomList) {
            if (CollectionUtils.isEmpty(room.getRoomTimeList())) continue;
            room.setRoomTimeList(
                    room.getRoomTimeList().stream().filter(t-> t.getStartTime().after(startTime)).collect(Collectors.toList())
            );

            if (CollectionUtils.isNotEmpty(room.getRoomTimeList())) ableList.add(room);
        }

        // 填充座位数据
        Map<String, List<RelRoomSeatEntity>> seatMap = seatList.stream().collect(Collectors.toMap(o-> o.getRoomTimeId(),
                o-> new ArrayList<RelRoomSeatEntity>() {{
                    add(o);
                }}, (k1, k2) -> {
                    k1.addAll(k2);
                    return k1;
                }));
        for (RoomEntity room : ableList) {
            room.getRoomTimeList().forEach(o-> {o.setSeatList(seatMap.get(o.getId()));});
        }


        return ableList;
    }


    /**
     * 抢座信息提交
     * @param seatId
     * @param phoneNumber
     * @param email
     */
    @Override
    public void submit(String seatId, String phoneNumber, String email) throws Exception {
        StringBuilder emailContext = new StringBuilder();
        String roomNo = "";
        String seatNo = "";

        // 新增用户或校验信用积分
        UserInfoEntity userInfo = userInfoService.lambdaQuery().eq(UserInfoEntity::getIsValid, 1).eq(UserInfoEntity::getPhoneNumber, phoneNumber).one();
        if (Objects.isNull(userInfo)){
            // 新增
            userInfoService.add(new UserInfoEntity().setPhoneNumber(phoneNumber));
        } else if (userInfo.getCreditScore() < 60){
            // 信用分用分低于60
            throw new Exception("预约失败,信用分用分低于60!");
        }

        ReservationEntity entity = new ReservationEntity().setId(IdWorker.getIdStr()).setStatus(1)
                                                          .setPhoneNumber(phoneNumber).setIsValid(1)
                                                          .setEmail(email);

        RelRoomSeatEntity seat = seatService.lambdaQuery().eq(RelRoomSeatEntity::getIsValid, 1).eq(RelRoomSeatEntity::getId, seatId).one();
        if (Objects.nonNull(seat)){
            // 设置教室,时段,座位信息
            seatNo = seat.getSeatNo();
            entity.setSeatId(seatId).setSeatNo(seat.getSeatNo());
            RelRoomTimeEntity time = timeService.lambdaQuery().eq(RelRoomTimeEntity::getIsValid, 1).eq(RelRoomTimeEntity::getId, seat.getRoomTimeId()).one();
            if (Objects.nonNull(time)){
                entity.setEndTime(time.getEndTime()).setStartTime(time.getStartTime());
            }

            RoomEntity room = roomService.lambdaQuery().eq(RoomEntity::getIsValid, 1).eq(RoomEntity::getId, seat.getRoomId()).one();
            if (Objects.nonNull(room)){
                roomNo = room.getRoomNo();
                entity.setRoomId(seat.getRoomId()).setSeatNo(room.getRoomNo());
            }

            // 发送邮箱
            emailContext.append("您预约了");
            emailContext.append(roomNo);
            emailContext.append("教室-");
            emailContext.append(seatNo);
            emailContext.append("座位, ");
            emailContext.append("请准时签到 !");
            emailService.sendEmali(email, emailContext.toString(), phoneNumber);

            // 保存
            this.save(entity);
        }

    }
}
